﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;

namespace AugustVisual
{
    public class AugustVisualizingStackPanel : VirtualizingPanel
    {

        public event EventHandler VerticleScrollBarShow;
        bool isactualChildHeight = false;
        public AugustVisualizingStackPanel()
        {
            Loaded += AugustVisualizingStackPanel_Loaded;
        }

        private void AugustVisualizingStackPanel_Loaded(object sender, RoutedEventArgs e)
        {
            SetVerticleOffset(0);
        }

        protected override void OnItemsChanged(object sender, ItemsChangedEventArgs args)
        {
            base.OnItemsChanged(sender, args);
            SetVerticleOffset(0);
        }

        protected override Size MeasureOverride(Size availableSize)
        {
            UIElementCollection children = InternalChildren;
            for (int childIndex = 0; childIndex < children.Count; childIndex++)
            {
                var child = children[childIndex];
                child.Measure(availableSize);
            }
            return base.MeasureOverride(availableSize);
        }



        protected override Size ArrangeOverride(Size finalSize)
        {
            containerHeight = finalSize.Height;
            UIElementCollection children = InternalChildren;
            ItemsControl itemsControl = ItemsControl.GetItemsOwner(this);
         
            for (int childIndex = 0; childIndex < children.Count; childIndex++)
            {
                var child = children[childIndex];
                // 通过数据
                var itemIndex = itemsControl.Items.IndexOf(((FrameworkElement)child).DataContext);
                if (itemIndex > -1)
                {
                    Size desiredSize = child.DesiredSize;
                    // 安排子元素布局
                    childHeight = desiredSize.Height;
                    isactualChildHeight = true;
                    child.Arrange(new Rect(0, desiredSize.Height * itemIndex - _offset, desiredSize.Width, desiredSize.Height));
                }
                else
                {
                    RemoveInternalChildRange(childIndex, 1);    // 移除子元素UI容器
                }
            }
            maxoffset = itemsControl.Items.Count * childHeight - containerHeight;
            Size size = new Size();
            size.Width = finalSize.Width + 1;
            size.Height = finalSize.Height + 1;
            return size;
        }

        private double _offset = 0d;
        private double childHeight = 10d;
        private double containerHeight = 10d;
        private double maxoffset = 0d;

        public double MaxOffset
        {
            get
            {
                return maxoffset;
            }
        }

        bool showFlag = false;

        public void SetVerticleOffset(double offset)
        {
            if (offset <= 0)
            {
                offset = 0;
            }

            else if (maxoffset <= offset)
            {
                offset = maxoffset;
            }

            _offset = offset;

            VirtualAllChid();

            int k = (int)(Math.Abs(offset) / childHeight);
            int l = (int)((Math.Abs(offset) + containerHeight) / childHeight) + 1;

            ItemsControl itemsControl = ItemsControl.GetItemsOwner(this);
            if (itemsControl.Items.Count < l)
            {
                l = itemsControl.Items.Count;
            }
            //Console.WriteLine(k.ToString() + "   " + l.ToString());
            for (int i = k; i < l; i++)
            {
                RealizeChild(i);
            }
            double actualHeight = (l - k) * childHeight;
            if (actualHeight >= containerHeight && isactualChildHeight&& !showFlag)
            {
                showFlag = true;
                VerticleScrollBarShow?.Invoke(this, EventArgs.Empty);
            }
            else
            {
                //showFlag = false;
                //VerticleScrollBarHide?.Invoke(this, EventArgs.Empty);
            }

        }


        /// <summary>
        /// 实例化子元素
        /// </summary>
        /// <param name="itemIndex">数据条目索引</param>
        public void RealizeChild(int itemIndex)
        {
            IItemContainerGenerator generator = this.ItemContainerGenerator;
            GeneratorPosition position = generator.GeneratorPositionFromIndex(itemIndex);
            IDisposable disposable = generator.StartAt(position, GeneratorDirection.Forward, true);

            bool isNewlyRealized;
            var child = (UIElement)generator.GenerateNext(out isNewlyRealized);
  
            if (isNewlyRealized)
            {
                AddInternalChild(child);
                generator.PrepareItemContainer(child);
                InvalidateMeasure();
                InvalidateArrange();
            }
            else
            {
            }
            disposable.Dispose();
        }

        /// <summary>
        /// 虚拟化子元素
        /// </summary>
        /// <param name="itemIndex">数据条目索引</param>
        public void VirtualizeChild(int itemIndex)
        {
            IItemContainerGenerator generator = this.ItemContainerGenerator;
            var childGeneratorPos = generator.GeneratorPositionFromIndex(itemIndex);
            if (childGeneratorPos.Offset == 0)
            {
                generator.Remove(childGeneratorPos, 1); // 虚拟化(从子元素UI容器中清除数据)
                InvalidateMeasure();
                InvalidateArrange();
            }
        }

        public void VirtualAllChid()
        {
       
            IItemContainerGenerator generator = this.ItemContainerGenerator;
            generator.RemoveAll();
            RemoveInternalChildRange(0, InternalChildren.Count);
            //var childGeneratorPos = generator.GeneratorPositionFromIndex(0);
            //generator.Remove(childGeneratorPos, InternalChildren.Count); // 虚拟化(从子元素UI容器中清除数据)
            //InvalidateMeasure();
            //InvalidateArrange();
        }


    }
}
